#ifndef __VECTOR_H__
#define __VECTOR_H__

#include <assert.h>
#include <xmmintrin.h>
#include "BasicType/BasicType_1.h"

namespace GCRE {
	namespace BasicType {

		//	------------------ Vector2 -----------------------------------------

		template <class T>
		class Vector2 {
			public:
				Vector2();
				Vector2( T x, T y );
				Vector2( const Vector2<T>& v );
		
				T& operator[]( SFInt i ) { assert( i >= 0 && i < 2 ); return data[i]; }
				T  operator[]( SFInt i ) const { assert( i >= 0 && i < 2 ); return data[i]; }
				SFDouble Length() const;
				void Set( T x, T y );
				void Normalize();
		
				T x() const { return data[0]; }
				T y() const { return data[1]; }
		
				Vector2<T>&							operator=( const Vector2<T>& v );
				Vector2<T>								operator+( const Vector2<T>& v ) const;
				Vector2<T>								operator-( const Vector2<T>& v ) const;
				Vector2<T>&							operator+=( const Vector2<T>& v );
				Vector2<T>&							operator-=( const Vector2<T>& v );
				SFDouble									operator*( const Vector2<T>& v ) const;
				Vector2<T>								operator*( SFDouble d ) const;
				Vector2<T>&							operator*=( SFDouble d );
				Vector2<T>								operator/( SFDouble d ) const;
				Vector2<T>&							operator/=( SFDouble d );
				Vector2<T>								operator-() const;
				friend Vector2<T>					operator*( SFDouble d, const Vector2<T>& v ) { return v * d; }

			protected:
		
			private:
				T data[2];
		};

		template <class T>
		void Vector2<T>::Set( T x, T y )
		{
			data[0] = x;
			data[1] = y;
		}

		template <class T>
		Vector2<T>::Vector2()
		{
			data[0] = data[1] = (T)0.0;
		}

		template <class T>
		Vector2<T>::Vector2( T x, T y )
		{
			data[0] = x;
			data[1] = y;
		}

		template <class T>
		Vector2<T>::Vector2( const Vector2<T>& v )
		{
			data[0] = v[0];
			data[1] = v[1];
		}

		template <class T>
		SFDouble Vector2<T>::Length() const
		{
			return sqrt( (SFDouble)(data[0] * data[0] + data[1] * data[1]) );
		}

		template <class T>
		void Vector2<T>::Normalize()
		{
			SFDouble length = sqrt( (SFDouble)(data[0] * data[0] + data[1] * data[1]) );
			data[0] = (T)( data[0] / length );
			data[1] = (T)( data[1] / length );
		}

		template <class T>
		Vector2<T>& Vector2<T>::operator=( const Vector2<T>& v )
		{
			data[0] = v[0];
			data[1] = v[1];
			return *this;
		}

		template <class T>
		SFDouble Vector2<T>::operator*( const Vector2<T>& v ) const
		{
			return (SFDouble)( data[0] * v[0] + data[1] * v[1] );
		}

		template <class T>
		Vector2<T>& Vector2<T>::operator-=( const Vector2<T>& v )
		{
			data[0] -= v[0];
			data[1] -= v[1];
			return *this;
		}

		template <class T>
		Vector2<T>& Vector2<T>::operator+=( const Vector2<T>& v )
		{
			data[0] += v[0];
			data[1] += v[1];
			return *this;
		}

		template <class T>
		Vector2<T> Vector2<T>::operator-( const Vector2<T>& v ) const
		{
			Vector2<T> temp;
			temp[0] = data[0] - v[0];
			temp[1] = data[1] - v[1];
			return temp;
		}

		template <class T>
		Vector2<T> Vector2<T>::operator+( const Vector2<T>& v ) const
		{
			Vector2<T> temp;
			temp[0] = data[0] + v[0];
			temp[1] = data[1] + v[1];
			return temp;
		}

		template <class T>
		Vector2<T> Vector2<T>::operator*( SFDouble d ) const
		{
			Vector2<T> temp;
			temp[0] = (T)( data[0] * d );
			temp[1] = (T)( data[1] * d );
			return temp;
		}

		template <class T>
		Vector2<T>& Vector2<T>::operator*=( SFDouble d )
		{
			data[0] = (T)( data[0] * d );
			data[1] = (T)( data[1] * d );
			return *this;
		}

		template <class T>
		Vector2<T> Vector2<T>::operator/( SFDouble d ) const
		{
			Vector2<T> temp;
			temp[0] = (T)( data[0] / d );
			temp[1] = (T)( data[1] / d );
			return temp;
		}

		template <class T>
		Vector2<T> Vector2<T>::operator-() const
		{
			Vector2<T> temp;
			temp[0] = -data[0];
			temp[1] = -data[1];
			return temp;
		}

		template <class T>
		Vector2<T>& Vector2<T>::operator/=( SFDouble d )
		{
			data[0] = (T)( data[0] / d );
			data[1] = (T)( data[1] / d );
			return *this;
		}

		//	------------------------------ Vector3 -----------------------------------------------

		template <class T>
		class Vector3 {
			public:
				Vector3();
				Vector3( T x, T y, T z );
				Vector3( const Vector3<T>& v );
	
				T& operator[]( SFInt i ) { assert( i >= 0 && i < 3 ); return data[i]; }
				T  operator[]( SFInt i ) const { assert( i >= 0 && i < 3 ); return data[i]; }
				SFDouble Length() const;
				void Normalize();
				void Set( T x, T y, T z );
				Vector3<T> Cross( const Vector3<T>& v ) const;
		
				T x() const { return data[0]; }
				T y() const { return data[1]; }
				T z() const { return data[2]; }
		
				Vector3<T>&							operator=( const Vector3<T>& v );
				Vector3<T>								operator+( const Vector3<T>& v ) const;
				Vector3<T>								operator-( const Vector3<T>& v ) const;
				Vector3<T>&							operator+=( const Vector3<T>& v );
				Vector3<T>&							operator-=( const Vector3<T>& v );
				SFDouble									operator*( const Vector3<T>& v ) const;
				Vector3<T>								operator*( SFDouble d ) const;
				Vector3<T>&							operator*=( SFDouble d );
				Vector3<T>								operator/( SFDouble d ) const;
				Vector3<T>&							operator/=( SFDouble d );
				Vector3<T>								operator-() const;
				friend Vector3<T>					operator*( SFDouble d, const Vector3<T>& v ) { return v * d; }

			protected:
		
			private:
				T data[3];
		};

		template <class T>
		void Vector3<T>::Set( T x, T y, T z )
		{
			data[0] = x;
			data[1] = y;
			data[2] = z;
		}

		template <class T>
		Vector3<T>::Vector3( const Vector3<T>& v )
		{
			data[0] = v[0];
			data[1] = v[1];
			data[2] = v[2];
		}

		template <class T>
		Vector3<T>::Vector3( T x, T y, T z )
		{
			data[0] = x;
			data[1] = y;
			data[2] = z;
		}

		template <class T>
		Vector3<T>::Vector3()
		{
			data[0] = data[1] = data[2] = (T)0.0;
		}

		template <class T>
		Vector3<T>& Vector3<T>::operator/=( SFDouble d )
		{
			data[0] = (T)( data[0] / d );
			data[1] = (T)( data[1] / d );
			data[2] = (T)( data[2] / d );
			return *this;
		}

		template <class T>
		Vector3<T> Vector3<T>::operator/( SFDouble d ) const
		{
			Vector3<T> temp;
			temp[0] = (T)( data[0] / d );
			temp[1] = (T)( data[1] / d );
			temp[2] = (T)( data[2] / d );
			return temp;
		}

		template <class T>
		Vector3<T>& Vector3<T>::operator*=( SFDouble d )
		{
			data[0] = (T)( data[0] * d );
			data[1] = (T)( data[1] * d );
			data[2] = (T)( data[2] * d );
			return *this;
		}

		template <class T>
		Vector3<T> Vector3<T>::operator*( SFDouble d ) const
		{
			Vector3<T> temp;
			temp[0] = (T)( data[0] * d );
			temp[1] = (T)( data[1] * d );
			temp[2] = (T)( data[2] * d );
			return temp;
		}

		template <class T>
		SFDouble Vector3<T>::operator*( const Vector3<T>& v ) const
		{
			return (SFDouble)( data[0] * v[0] + data[1] * v[1] + data[2] * v[2] );
		}

		template <class T>
		Vector3<T>& Vector3<T>::operator-=( const Vector3<T>& v )
		{
			data[0] -= v[0];
			data[1] -= v[1];
			data[2] -= v[2];
			return *this;
		}

		template <class T>
		Vector3<T>& Vector3<T>::operator+=( const Vector3<T>& v )
		{
			data[0] += v[0];
			data[1] += v[1];
			data[2] += v[2];
			return *this;
		}

		template <class T>
		Vector3<T> Vector3<T>::operator-( const Vector3<T>& v ) const
		{
			Vector3<T> temp;
			temp[0] = data[0] - v[0];
			temp[1] = data[1] - v[1];
			temp[2] = data[2] - v[2];
			return temp;
		}

		template <class T>
		Vector3<T> Vector3<T>::operator+( const Vector3<T>& v ) const
		{
			Vector3<T> temp;
			temp[0] = data[0] + v[0];
			temp[1] = data[1] + v[1];
			temp[2] = data[2] + v[2];
			return temp;
		}

		template <class T>
		Vector3<T>& Vector3<T>::operator=( const Vector3<T>& v )
		{
			data[0] = v[0]; data[1] = v[1]; data[2] = v[2];
			return *this;
		}

		template <class T>
		Vector3<T> Vector3<T>::Cross( const Vector3<T>& v ) const
		{
			Vector3<T> temp;
			temp[0] = data[1] * v[2] - data[2] * v[1];
			temp[1] = data[2] * v[0] - data[0] * v[2];
			temp[2] = data[0] * v[1] - data[1] * v[0];
			return temp;
		}

		template <class T>
		void Vector3<T>::Normalize()
		{
			SFDouble length = sqrt( (SFDouble)( data[0] * data[0] + data[1] * data[1] + data[2] * data[2] ) );
			data[0] = (T)( data[0] / length );
			data[1] = (T)( data[1] / length );
			data[2] = (T)( data[2] / length );
		}

		template <class T>
		Vector3<T> Vector3<T>::operator-() const
		{
			Vector3<T> temp;
			temp[0] = -data[0];
			temp[1] = -data[1];
			temp[2] = -data[2];
			return temp;
		}

		template <class T>
		SFDouble Vector3<T>::Length() const
		{
			return sqrt( (SFDouble)( data[0] * data[0] + data[1] * data[1] + data[2] * data[2] ) );
		}

		//	------------------------------ Vector4 -----------------------------------------------

		template <class T>
		class Vector4 {
			public:
				Vector4();
				Vector4( const Vector4<T>& v );
				Vector4( T x, T y, T z, T w );
				Vector4( const Vector3<T>& v3, SFDouble w = 1.0 );
	
				T& operator[]( SFInt i ) { assert( i >= 0 && i < 4 ); return data[i]; }
				T  operator[]( SFInt i ) const { assert( i >= 0 && i < 4 ); return data[i]; }
				SFDouble Length() const;
				void Set( T x, T y, T z, T w );
				void Normalize();
				Vector4<T> Cross( const Vector4<T>& v ) const;
		
				T x() const { return data[0]; }
				T y() const { return data[1]; }
				T z() const { return data[2]; }
				T w() const { return data[3]; }
		
				Vector4<T>&								operator=( const Vector4<T>& v );
				Vector4<T>									operator+( const Vector4<T>& v ) const;
				Vector4<T>									operator-( const Vector4<T>& v ) const;
				Vector4<T>									operator-() const;
				Vector4<T>&								operator+=( const Vector4<T>& v );
				Vector4<T>&								operator-=( const Vector4<T>& v );
				Vector4<T>									operator/( SFDouble d ) const;
				Vector4<T>&								operator/=( SFDouble d );
				Vector4<T>									operator*( SFDouble d ) const;
				Vector4<T>&								operator*=( SFDouble d );
				friend Vector4<T>						operator*( SFDouble d, const Vector4<T>& v ) { return v * d; }

			protected:
		
			private:
				T data[4];
		};

		template <class T>
		Vector4<T> Vector4<T>::operator-() const
		{
			Vector4<T> temp;
			temp.data[0] = -data[0];
			temp.data[1] = -data[1];
			temp.data[2] = -data[2];
			temp.data[3] = -data[3];
			return temp;
		}

		template <class T>
		void Vector4<T>::Set( T x, T y, T z, T w )
		{
			data[0] = x;
			data[1] = y;
			data[2] = z;
			data[3] = w;
		}

		template <class T>
		Vector4<T> Vector4<T>::Cross( const Vector4<T>& v ) const
		{
			assert( data[3] == 0.0 && v[3] == 0.0 );
			Vector4<T> temp;
			temp[0] = data[1] * v[2] - data[2] * v[1];
			temp[1] = data[2] * v[0] - data[0] * v[2];
			temp[2] = data[0] * v[1] - data[1] * v[0];
			temp[3] = (T)0.0;
			return temp;
		}

		template <class T>
		Vector4<T>::Vector4()
		{
			data[0] = data[1] = data[2] = data[3] = (T)0.0;
		}

		template <class T>
		Vector4<T>::Vector4( T x, T y, T z, T w )
		{
			data[0] = x; data[1] = y; data[2] = z; data[3] = w;
		}

		template <class T>
		Vector4<T>::Vector4( const Vector4<T>& v )
		{
			data[0] = v[0]; data[1] = v[1]; data[2] = v[2]; data[3] = v[3];
		}

		template <class T>
		Vector4<T>::Vector4( const Vector3<T>& v3, SFDouble w /*= 1.0 */ )
		{
			data[0] = v3[0]; data[1] = v3[1]; data[2] = v3[2]; data[3] = (T)w;
		}

		template <class T>
		SFDouble Vector4<T>::Length() const
		{
			assert( data[3] == 0.0 );
			return sqrt( (SFDouble)( data[0] * data[0] + data[1] * data[1] + data[2] * data[2] ) );
		}

		template <class T>
		void Vector4<T>::Normalize()
		{
			assert( data[3] == 0.0 );
			SFDouble length = sqrt( (SFDouble)( data[0] * data[0] + data[1] * data[1] + data[2] * data[2] ) );
			data[0] = (T)( data[0] / length );
			data[1] = (T)( data[1] / length );
			data[2] = (T)( data[2] / length );
		}

		template <class T>
		Vector4<T>& Vector4<T>::operator=( const Vector4<T>& v )
		{
			data[0] = v[0]; data[1] = v[1]; data[2] = v[2]; data[3] = v[3];
			return *this;
		}

		template <class T>
		Vector4<T> Vector4<T>::operator+( const Vector4<T>& v ) const
		{
			Vector4<T> temp;
			temp[0] = data[0] + v[0];
			temp[1] = data[1] + v[1];
			temp[2] = data[2] + v[2];
			temp[3] = data[3] + v[3];
			return temp;
		}

		template <class T>
		Vector4<T> Vector4<T>::operator-( const Vector4<T>& v ) const
		{
			Vector4<T> temp;
			temp[0] = data[0] - v[0];
			temp[1] = data[1] - v[1];
			temp[2] = data[2] - v[2];
			temp[3] = data[3] - v[3];
			return temp;
		}

		template <class T>
		Vector4<T>& Vector4<T>::operator+=( const Vector4<T>& v )
		{
			data[0] += v[0]; data[1] += v[1]; data[2] += v[2]; data[3] += v[3];
			return *this;
		}

		template <class T>
		Vector4<T>& Vector4<T>::operator-=( const Vector4<T>& v )
		{
			data[0] -= v[0]; data[1] -= v[1]; data[2] -= v[2]; data[3] -= v[3];
			return *this;
		}

		template <class T>
		Vector4<T> Vector4<T>::operator/( SFDouble d ) const
		{
			Vector4<T> temp;
			temp[0] = (T)( data[0] / d );
			temp[1] = (T)( data[1] / d );
			temp[2] = (T)( data[2] / d );
			temp[3] = (T)( data[3] / d );
			return temp;
		}

		template <class T>
		Vector4<T>& Vector4<T>::operator/=( SFDouble d )
		{
			data[0] = (T)( data[0] / d );
			data[1] = (T)( data[1] / d );
			data[2] = (T)( data[2] / d );
			data[3] = (T)( data[3] / d );
			return *this;
		}

		template <class T>
		Vector4<T> Vector4<T>::operator*( SFDouble d ) const
		{
			Vector4<T> temp;
			temp[0] = (T)( data[0] * d );
			temp[1] = (T)( data[1] * d );
			temp[2] = (T)( data[2] * d );
			temp[3] = (T)( data[3] * d );
			return temp;
		}

		template <class T>
		Vector4<T>& Vector4<T>::operator*=( SFDouble )
		{
			data[0] = (T)( data[0] * d );
			data[1] = (T)( data[1] * d );
			data[2] = (T)( data[2] * d );
			data[3] = (T)( data[3] * d );
			return *this;
		}
		//	============	Type def			===================

		typedef Vector2<SFInt> Vec2i;
		typedef Vector2<SFFloat> Vec2f;
		typedef Vector2<SFDouble> Vec2d;

		typedef Vector3<SFInt> Vec3i;
		typedef Vector3<SFFloat> Vec3f;
		typedef Vector3<SFDouble> Vec3d;

		typedef Vector4<SFDouble> Vec4d;

		//	============	Vector4f SSE		===================

		class Matrix44f;

		class Vec4f {
			friend Matrix44f;
			public:
				Vec4f();
				Vec4f( const Vec4f& v );
				Vec4f( SFFloat x, SFFloat y, SFFloat z, SFFloat w = 1.0f );
				Vec4f( const Vec3f& v3, SFFloat w = 1.0f );

				SFFloat& operator[]( SFInt i ) { assert( i >= 0 && i < 4 ); return data[i]; }
				SFFloat  operator[]( SFInt i ) const { assert( i >= 0 && i < 4 ); return data[i]; }
				SFFloat Length() const;
				void Set( SFFloat x, SFFloat y, SFFloat z, SFFloat w );
				void Normalize();
				Vec4f Cross( const Vec4f& v ) const;

				SFFloat x() const { return data[0]; }
				SFFloat y() const { return data[1]; }
				SFFloat z() const { return data[2]; }
				SFFloat w() const { return data[3]; }

				void*							operator new( size_t size );
				void								operator delete( void *mem );
				void*							operator new[]( size_t size );
				void								operator delete[]( void *mem );

				Vec4f&								operator=( const Vec4f& v );
				Vec4f								operator+( const Vec4f& v ) const;
				Vec4f								operator-( const Vec4f& v ) const;
				Vec4f								operator-() const;
				Vec4f&								operator+=( const Vec4f& v );
				Vec4f&								operator-=( const Vec4f& v );
				Vec4f								operator/( SFFloat f ) const;
				Vec4f&								operator/=( SFFloat f );
				Vec4f								operator*( SFFloat f ) const;
				Vec4f&								operator*=( SFFloat f );
				SFFloat								operator*( const Vec4f& v ) const;
				friend Vec4f						operator*( SFFloat f, const Vec4f& v ) { return v * f; }
				friend Vec4f						operator*( const Vec4f& v, const Matrix44f& m );

			protected:

			private:
				union {
					__m128		vec;
					SFFloat			data[4];
				};
		};

		inline Vec4f::Vec4f()
		{
			vec = _mm_set_ps1( 0.0f );
		}

		inline Vec4f::Vec4f( const Vec4f& v )
		{
			vec = v.vec;
		}

		inline Vec4f::Vec4f( SFFloat x, SFFloat y, SFFloat z, SFFloat w /* = 1.0f */  )
		{
			vec = _mm_set_ps( w, z, y, x );
		}

		inline Vec4f::Vec4f( const Vec3f& v3, SFFloat w /*= 1.0f */ )
		{
			vec = _mm_set_ps( w, v3[2], v3[1], v3[0] );
		}

		inline SFFloat Vec4f::Length() const
		{
			SFFloat length;

			__m128 r1 = _mm_mul_ps( vec, vec ); // r1 = (x*x, y*y, z*z, w*w)
			__m128 r2 = _mm_shuffle_ps( r1, r1, _MM_SHUFFLE(1,1,1,1) ); // r2 = (r1.y, r1.y, r1.y, r1.y)
			__m128 r3 = _mm_shuffle_ps( r1, r1, _MM_SHUFFLE(2,2,2,2) ); // r3 = (r1.z, r1.z, r1.z, r1.z)

			r2 = _mm_add_ss( r1, r2 ); // r2.x += r1.x = x*x + y*y;
			r2 = _mm_add_ss( r3, r2 ); // r2.x += r3.x = x*x + y*y * z*z;

			__m128 r4 = _mm_sqrt_ss( r2 );
			_mm_store_ss( &length, r4 );

			return length;
		}

		inline void Vec4f::Normalize()
		{
			__m128 r1 = _mm_mul_ps( vec, vec ); // r1 = (x*x, y*y, z*z, w*w)
			__m128 r2 = _mm_shuffle_ps( r1, r1, _MM_SHUFFLE(1,1,1,1) ); // r2 = (r1.y, r1.y, r1.y, r1.y)
			__m128 r3 = _mm_shuffle_ps( r1, r1, _MM_SHUFFLE(2,2,2,2) ); // r3 = (r1.z, r1.z, r1.z, r1.z)

			r2 = _mm_add_ss( r1, r2 ); // r2.x += r1.x = x*x + y*y;
			r2 = _mm_add_ss( r3, r2 ); // r2.x += r3.x = x*x + y*y * z*z;

			__m128 r4 = _mm_rsqrt_ss( r2 );
			r4 = _mm_shuffle_ps( r4, r4, _MM_SHUFFLE(0, 0, 0, 0) );
			vec = _mm_mul_ps( vec, r4 );
		}

		inline Vec4f Vec4f::Cross( const Vec4f& v ) const
		{
			Vec4f result;
			__m128 r0, r1, r2, r3;

			// Shuffles
			//					  w  y   z  x
			// w | x | z | y  == 11 00  10 01 = 0xC9 
			// w | y | x | z  == 11 01  00 10 = 0xD2

			r0 = _mm_shuffle_ps( vec, vec, 0xc9 );
			r1 = _mm_shuffle_ps( v.vec, v.vec, 0xd2 );
			r2 = _mm_shuffle_ps( vec, vec, 0xd2 );
			r3 = _mm_shuffle_ps( v.vec, v.vec, 0xc9 );

			r1 = _mm_mul_ps( r0, r1 );
			r3 = _mm_mul_ps( r2, r3 );
			r2 = _mm_sub_ps( r1, r3 );

			result.vec = r2;
			return result;
		}

		inline Vec4f& Vec4f::operator=( const Vec4f& v )
		{
			vec = v.vec;
			return *this;
		}

		inline Vec4f Vec4f::operator+( const Vec4f& v ) const
		{
			Vec4f result;
			result.vec = _mm_add_ps( vec, v.vec );
			return result;
		}

		inline Vec4f Vec4f::operator-( const Vec4f& v ) const
		{
			Vec4f result;
			result.vec = _mm_sub_ps( vec, v.vec );
			return result;
		}

		inline Vec4f& Vec4f::operator+=( const Vec4f& v )
		{
			vec = _mm_add_ps( vec, v.vec );
			return *this;
		}

		inline Vec4f& Vec4f::operator-=( const Vec4f& v )
		{
			vec = _mm_sub_ps( vec, v.vec );
			return *this;
		}

		inline Vec4f Vec4f::operator/( SFFloat f ) const
		{
			Vec4f result;
			__m128 ffff = _mm_set_ps1( f );
			result.vec = _mm_div_ps( vec, ffff );
			return result;
		}

		inline Vec4f& Vec4f::operator/=( SFFloat f )
		{
			__m128 ffff = _mm_set_ps1( f );
			vec = _mm_div_ps( vec, ffff );
			return *this;
		}

		inline Vec4f Vec4f::operator*( SFFloat f ) const
		{
			Vec4f result;
			__m128 ffff = _mm_set_ps1( f );
			result.vec = _mm_mul_ps( vec, ffff );
			return result;
		}

		inline SFFloat Vec4f::operator*( const Vec4f& v ) const
		{
			SFFloat result;
			__m128 r1 = _mm_mul_ps( vec,v.vec ); // r1 = (x*x, y*y, z*z, w*w)
			__m128 r2 = _mm_shuffle_ps( r1, r1, _MM_SHUFFLE(1,1,1,1) ); // r2 = (r1.y, r1.y, r1.y, r1.y)
			__m128 r3 = _mm_shuffle_ps( r1, r1, _MM_SHUFFLE(2,2,2,2) ); // r3 = (r1.z, r1.z, r1.z, r1.z)

			r2 = _mm_add_ss( r1, r2 ); // r2.x += r1.x = x*x + y*y;
			r2 = _mm_add_ss( r3, r2 ); // r2.x += r3.x = x*x + y*y * z*z;

			_mm_store_ss( &result, r2 );

			return result;
		}

		inline Vec4f& Vec4f::operator*=( SFFloat f )
		{
			__m128 ffff = _mm_set_ps1( f );
			vec = _mm_mul_ps( vec, ffff );
			return *this;
		}

		inline void Vec4f::Set( SFFloat x, SFFloat y, SFFloat z, SFFloat w )
		{
			vec = _mm_set_ps( w, z, y, x );
		}

		inline Vec4f Vec4f::operator-() const
		{
			Vec4f result;
			__m128 zero = _mm_set_ps1( 0.0F );
			result.vec = _mm_sub_ps( zero, vec );
			return result;
		}

		inline void* Vec4f::operator new( size_t size )
		{
			return _mm_malloc( size, 16 );
		}

		inline void* Vec4f::operator new[]( size_t size )
		{
			return _mm_malloc( size, 16 );
		}

		inline void Vec4f::operator delete[]( void *mem )
		{
			_mm_free( mem );
		}

		inline void Vec4f::operator delete( void *mem )
		{
			_mm_free( mem );
		}

	}
}
#endif	//	__VECTOR_H__